package com.qqt.csr.common.utils;

import com.qqt.csr.common.exception.BaseException;
import com.qqt.csr.common.exception.StatusCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * @author:
 * @date: 2024-05-24 17:03
 */
@Slf4j
@Component
public class RedissonLockUtil {
    private final RedissonClient redissonClient;

    public RedissonLockUtil(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    public <T> T distributedLock(Supplier<T> supplier, String lockKey, long waitTime, long leaseTime, TimeUnit unit) {
        RLock lock = null;
        boolean isLock = false;
        try {
            lock = redissonClient.getLock(lockKey);
            isLock = lock.tryLock(waitTime, leaseTime, unit);
            if (!isLock) {
                return null;
            }
            return supplier.get();
        } catch (InterruptedException e) {
            log.error("获取分布式锁失败，线程被中断！lockKey:{}", lockKey, e);
            throw new BaseException(StatusCode.INTERNAL_SERVER_ERROR);
        } finally {
            if(lock != null && isLock && lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
    }

    public void distributedLock(Runnable runnable, String lockKey, long waitTime, long leaseTime, TimeUnit unit) {
        distributedLock(() -> {
            runnable.run();
            return null;
        }, lockKey, waitTime, leaseTime, unit);
    }

    public void distributedLock(Runnable runnable, String lockKey) {
        distributedLock(runnable, lockKey, 0, 0, TimeUnit.SECONDS);
    }

    public <T> T distributedLock(Supplier<T> supplier, String lockKey) {
        return distributedLock(supplier, lockKey, 0, 0, TimeUnit.SECONDS);
    }
}
